home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 2 / ACE CD 2.iso / FILES / UTILS / GAMESDS3.DMS / GAMESDS3.adf / GDS_Examples.lha / Examples / bubble / bubble_line.c < prev    next >
C/C++ Source or Header  |  1994-11-14  |  19KB  |  566 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <exec/memory.h>
  5. #include <exec/types.h>
  6. #include <graphics/gfx.h>
  7. #include <graphics/gfxbase.h>
  8.  
  9. #include <proto/exec.h>
  10. #include <proto/graphics.h>
  11.  
  12. #include "GameSmith:GameSmith.h"
  13. #include "GameSmith:include/libraries/libptrs.h"
  14. #include "bubble.h"
  15.  
  16. /*-------------------------------------------------------------------------*/
  17.  
  18. #define VIDEO_STEPS      30
  19. #define COLOR_GRADIENT   0x100            /* color change amount */
  20. #define VIDEO_REG         0x180            /* address of bg color reg */
  21. #define BGCOLOR         0xf00            /* max color value (bright red) */
  22. #define BGCOLOR_LONG      0x00ff0000      /* 8 bit color entry (bright red) */
  23. #define MIN_COLOR         0x000
  24.  
  25. /*-------------------------------------------------------------------------*/
  26. /* Function Prototypes                                                      */
  27.  
  28. void parser(int,char **);
  29. int setup(void);
  30. void build_copper(void);
  31. void move_image(void);
  32. void check_bounds(void);
  33. __stdargs void collision(struct anim_struct *,struct anim_struct *,
  34.      struct collision_struct *,struct collision_struct *);
  35. int check_close(void);
  36. void cleanup(void);
  37. void free_arrays(void);
  38.  
  39. /*-------------------------------------------------------------------------*/
  40. /* some global variables                                                   */
  41.  
  42. int bubble_cnt,swidth,sheight,smode,delay=0,random_x=11,random_y=9;
  43. int *x=NULL,*y=NULL,*speedx=NULL,*speedy=NULL,*reset=NULL,*last=NULL;
  44. int dlist;                        /* display list handle for anims */
  45.  
  46. int display_page=0;
  47. struct anim_struct *bubble;
  48. int copheight;
  49.  
  50. /*-------------------------------------------------------------------------*/
  51.  
  52. unsigned short copper_list[256];   /* enough for our custom copper list */
  53.  
  54. struct gs_viewport vp =
  55.    {
  56.    NULL,                           /* ptr to next viewport */
  57.    NULL,                           /* ptr to color table */
  58.    0,                              /* number of colors in table */
  59.    copper_list,                  /* ptr to user copper list for both pages */
  60.    0,0,0,0,0,                     /* height, width, depth, bmheight, bmwidth */
  61.    0,0,                           /* top & left viewport offsets */
  62.    0,0,                           /* X & Y bitmap offsets */
  63.    GSVP_ALLOCBM,                  /* flags (alloc bitmaps) */
  64.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  65.    NULL,NULL,                     /* bitmap pointers */
  66.    NULL,                           /* future expansion */
  67.    0,0,0,0                        /* display clip (use nominal) */
  68.    };
  69.  
  70. struct display_struct bubble_display =
  71.    {
  72.    NULL,                           /* ptr to previous display view */
  73.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  74.    0,0,                           /* X and Y display offsets */
  75.    0,                              /* display mode ID */
  76.    4,4,                           /* sprite priorities (sprites in front of playfields) */
  77.    GSV_DOUBLE,                     /* flags */
  78.    &vp,                           /* ptr to 1st viewport */
  79.    NULL                           /* future expansion */
  80.    };
  81.  
  82. /***************************************************************************/
  83.  
  84. main(argc,argv)
  85. int argc;
  86. char *argv[];
  87.  
  88. {
  89.    int err,end=0;
  90.  
  91.    if (argc < 2)
  92.       {
  93.       printf("\nUSAGE: bubbles [number of bubbles] [HIRES] [SUPER] [VB delay intervals] [X speed] [Y speed]\n");
  94.       exit(01);
  95.       }
  96.    if (gs_open_libs(DOS|GRAPHICS,0))   /* open AmigaDOS libs */
  97.       exit(01);               /* if can't open libs, abort */
  98.    parser(argc,argv);         /* parse command line args */
  99.    if (err=setup())            /* if couldn't get set up... abort program */
  100.       {
  101.       printf("\nSetup error: %d\n",err);
  102.       gs_close_libs();         /* close all libraries */
  103.       exit(02);
  104.       }
  105.    Forbid();                  /* take over the entire machine */
  106.    while (!end)               /* this shows off speed */
  107.       {
  108.       move_image();            /* move them bubbles around */
  109.       end=check_close();      /* end when user hits left mouse button */
  110.       }
  111.    Permit();                  /* OK, let other things run while we clean up */
  112.    cleanup();                  /* close & deallocate everything */
  113.    gs_close_libs();            /* close all libraries */
  114. }
  115.  
  116. /***************************************************************************/
  117.  
  118. void parser(argc,argv)
  119. int argc;
  120. char *argv[];
  121.  
  122. {
  123.    bubble_cnt=atoi(argv[1]);   /* # anims to place on the screen */
  124.    swidth=320;                  /* default width & height */
  125.    sheight=200;
  126.    copheight=200;
  127.    smode=0;                     /* default mode of lores no lace */
  128.    #ifdef NTSC_MONITOR_ID
  129.       if (GfxBase->LibNode.lib_Version >= 36)   /* if WB 2.0 or higher */
  130.          {               /* this defeats mode promotion on AGA machines */
  131.          if (ModeNotAvailable(NTSC_MONITOR_ID))
  132.             {
  133.             smode = PAL_MONITOR_ID;
  134.             sheight=256;
  135.             copheight=256;
  136.             }
  137.          else
  138.             {
  139.             smode = NTSC_MONITOR_ID;
  140.             }
  141.          }
  142.    #endif
  143.    if (argc >= 3)
  144.       {
  145.       if (!(stricmp(argv[2],"DBL")))   /* check for double scan */
  146.          {
  147.          #ifdef DBLNTSC_MONITOR_ID
  148.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  149.             {               /* try for mode promoted AGA display */
  150.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  151.                {
  152.                smode = DBLNTSC_MONITOR_ID;
  153.                copheight=400;
  154.                }
  155.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  156.                {
  157.                smode = DBLPAL_MONITOR_ID;
  158.                sheight=256;
  159.                copheight=512;
  160.                }
  161.             }
  162.          #endif
  163.          }
  164.       else if (!(stricmp(argv[2],"DBLHIRES")))   /* check for hires double scan */
  165.          {
  166.          #ifdef DBLNTSC_MONITOR_ID
  167.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  168.             {               /* try for mode promoted AGA display */
  169.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  170.                {
  171.                swidth=640;
  172.                smode = DBLNTSC_MONITOR_ID;
  173.                copheight=400;
  174.                sheight=400;
  175.                }
  176.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  177.                {
  178.                swidth=640;
  179.                smode = DBLPAL_MONITOR_ID;
  180.                sheight=256;
  181.                copheight=512;
  182.                }
  183.             smode|=HIRES|LACE;
  184.             }
  185.          #endif
  186.          }
  187.       else if (!(stricmp(argv[2],"HIRES")))   /* check for hires spec */
  188.          {
  189.          swidth=640;
  190.          sheight=400;
  191.          smode|=HIRES|LACE;
  192.          }
  193.       else if (!(stricmp(argv[2],"SUPER")))   /* check for superhires72 */
  194.          {
  195.          #ifdef SUPER72_MONITOR_ID
  196.          if (GfxBase->LibNode.lib_Version >= 36)
  197.             {
  198.             if (!ModeNotAvailable(SUPER72_MONITOR_ID | SUPERLACE_KEY))
  199.                {
  200.                smode=SUPER72_MONITOR_ID | SUPERLACE_KEY;
  201.                swidth=800;
  202.                sheight=600;
  203.                copheight=300;
  204.                }
  205.             }
  206.          #endif
  207.          }
  208.       }
  209.    if (argc >= 4)
  210.       {
  211.       delay=atoi(argv[3]);      /* delay value in vertical blank intervals */
  212.       }
  213.    if (argc >= 5)               /* new random X speed range */
  214.       {
  215.       random_x=atoi(argv[4]);
  216.       if (random_x < 2)
  217.          random_x=2;
  218.       }
  219.    if (argc >= 6)               /* new random Y speed range */
  220.       {
  221.       random_y=atoi(argv[5]);
  222.       if (random_y < 2)
  223.          random_y=2;
  224.       }
  225. }
  226.  
  227. /***************************************************************************/
  228.  
  229. int setup()
  230.  
  231. {
  232.    int cnt,depth=0;
  233.    struct blit_struct *img;
  234.    struct anim_load_struct load;
  235.  
  236.    if (!(x=(int *)malloc(bubble_cnt*sizeof(int))))
  237.       return(-1);
  238.    if (!(y=(int *)malloc(bubble_cnt*sizeof(int))))
  239.       {
  240.       free_arrays();
  241.       return(-1);
  242.       }
  243.    if (!(speedx=(int *)malloc(bubble_cnt*sizeof(int))))
  244.       {
  245.       free_arrays();
  246.       return(-1);
  247.       }
  248.    if (!(speedy=(int *)malloc(bubble_cnt*sizeof(int))))
  249.       {
  250.       free_arrays();
  251.       return(-1);
  252.       }
  253.    if (!(last=(int *)malloc(bubble_cnt*sizeof(int))))
  254.       {
  255.       free_arrays();
  256.       return(-1);
  257.       }
  258.    if (!(reset=(int *)malloc(bubble_cnt*sizeof(int))))
  259.       {
  260.       free_arrays();
  261.       return(-1);
  262.       }
  263.    load.filename="bubble2";         /* name of anim file */
  264.    load.cmap_size=8;                  /* number of bits per color value */
  265.    load.array_elements=bubble_cnt;   /* number of array elements desired */
  266.    load.flags=0L;                     /* no special load flags */
  267.    if (gs_load_anim(&load))         /* load the anim object */
  268.       {
  269.       free_arrays();
  270.       return(-1);
  271.       }
  272.    bubble=load.anim_ptr.anim;         /* ptr to bubble anim */
  273.    if (load.type)                     /* make sure it's an anim type */
  274.       {
  275.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  276.       free_arrays();
  277.       if (load.type = 1)
  278.          gs_free_cplx((struct anim_cplx *)bubble,bubble_cnt);
  279.       return(-2);
  280.       }
  281.    img = bubble[0].list;            /* ptr to 1st image in anim sequence */
  282.    while (img)                        /* find max depth of anim */
  283.       {
  284.       if (img->depth > depth)
  285.          depth = img->depth;
  286.       if (img->next == img)         /* avoid infinite loop */
  287.          img=NULL;                  /* if single shot anim */
  288.       else
  289.          img=img->next;
  290.       }
  291.    vp.height = sheight;               /* set up display dimensions */
  292.    vp.width = swidth;
  293.    vp.depth = depth;
  294.    vp.bmheight = sheight;
  295.    vp.bmwidth = swidth;
  296.    bubble_display.modes = smode;
  297.    vp.num_colors=load.cmap_entries;
  298.    vp.color_table=load.cmap;         /* addr of color table */
  299.    build_copper();                  /* build custom copper list */
  300.    load.cmap[0]=BGCOLOR_LONG;         /* use our new background color */
  301.    if (gs_create_display(&bubble_display))
  302.       {
  303.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  304.       free_arrays();
  305.       gs_free_anim(bubble,bubble_cnt);
  306.       return(-2);
  307.       }
  308.    FreeMem(load.cmap,load.cmap_entries*sizeof(long));   /* done with color table */
  309.    if ((dlist=gs_get_display_list()) < 0)   /* allocate a display list for anims */
  310.       {
  311.       free_arrays();
  312.       gs_free_anim(bubble,bubble_cnt);
  313.       return(-3);
  314.       }
  315.    gs_init_anim(dlist,vp.bitmap1,vp.bitmap2,NULL);   /* tell anim system about bitmaps */
  316.    gs_set_anim_bounds(dlist,0,0,swidth-1,sheight-1);   /* set bounds for anim objects */
  317.    gs_set_collision(dlist,&collision);   /* set ptr to collision handler */
  318.    for (cnt=0; cnt < bubble_cnt; cnt++)
  319.       {                              /* add all bubbles to a display list */
  320.       reset[cnt]=0;
  321.       last[cnt]=-1;
  322.       x[cnt] = gs_random(swidth);   /* random X,Y coords */
  323.       y[cnt] = gs_random(sheight);
  324.       while ((speedx[cnt] = gs_random(random_x)) == 0);
  325.       while ((speedy[cnt] = gs_random(random_y)) == 0);
  326.       if (cnt&1)
  327.          {
  328.          speedx[cnt]*=-1;
  329.          speedy[cnt]*=-1;
  330.          }
  331.       if (gs_add_anim(dlist,(struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]))
  332.          {
  333.          cleanup();                  /* release everything */
  334.          return(-4);                  /* return failure */
  335.          }
  336.       gs_set_anim_cell((struct anim_struct *)&bubble[cnt],gs_random(bubble[cnt].count));
  337.       }
  338.    gs_draw_anims(dlist);
  339.    check_bounds();
  340.    gs_next_anim_page(dlist);
  341.    gs_show_display(&bubble_display,1);
  342.    gs_flip_display(&bubble_display,1);
  343.    display_page^=1;                  /* keep track of current display page */
  344.    gs_open_vb_timer();
  345.    return(0);
  346. }
  347.  
  348. /***************************************************************************/
  349.  
  350. void build_copper()
  351.  
  352. /* build a custom copper list of background color changes */
  353.  
  354. {
  355.    int cnt,cnt2=0,video_gradient;
  356.    short bgcolor,gradient,ctable[15];
  357.  
  358.    bgcolor=BGCOLOR;
  359.    gradient=0;
  360.    video_gradient=(copheight/3)/15;
  361.    for (cnt=0; cnt < 15; cnt++)            /* build copper list */
  362.       {
  363.       if (cnt)
  364.          {
  365.          copper_list[cnt2++]=UC_WAIT;      /* copper wait instruction */
  366.          copper_list[cnt2++]=gradient;      /* y coord to wait on */
  367.          copper_list[cnt2++]=0;            /* x coord to wait on */
  368.          }
  369.       ctable[cnt]=bgcolor;
  370.       copper_list[cnt2++]=UC_SETCOLOR;      /* set color register */
  371.       copper_list[cnt2++]=0;               /* register number */
  372.       copper_list[cnt2++]=ctable[cnt];      /* value for register */
  373.       gradient+=video_gradient;
  374.       bgcolor-=COLOR_GRADIENT;
  375.       if (bgcolor < MIN_COLOR)
  376.          bgcolor=0;
  377.       }
  378.    copper_list[cnt2++]=UC_WAIT;            /* copper wait instruction */
  379.    copper_list[cnt2++]=gradient;            /* y coord to wait on */
  380.    copper_list[cnt2++]=0;                  /* x coord to wait on */
  381.    copper_list[cnt2++]=UC_SETCOLOR;
  382.    copper_list[cnt2++]=0;                  /* color number */
  383.    copper_list[cnt2++]=0;                  /* color value */
  384.    gradient=((copheight/3)*2)-video_gradient;   /* build bottom color gradient */
  385.    for (cnt=14; cnt >= 0; cnt--)            /* build copper list */
  386.       {
  387.       copper_list[cnt2++]=UC_WAIT;         /* copper wait instruction */
  388.       copper_list[cnt2++]=gradient;         /* y coord to wait on */
  389.       copper_list[cnt2++]=0;               /* x coord to wait on */
  390.       copper_list[cnt2++]=UC_SETCOLOR;      /* set color register */
  391.       copper_list[cnt2++]=0;               /* register number */
  392.       copper_list[cnt2++]=ctable[cnt];      /* value for register */
  393.       gradient+=video_gradient;
  394.       }
  395.    copper_list[cnt2++]=UC_END;            /* end coppper list */
  396. }
  397.  
  398. /***************************************************************************/
  399.  
  400. void move_image()
  401.  
  402. /* move and animate the graphic objects on the screen */
  403.  
  404. {
  405.    static int x1,y1,lastx,lasty,new_line=1,first=1;
  406.    int cnt;
  407.  
  408.    if (gs_vb_time() < delay)
  409.       return;
  410.    gs_vb_timer_reset();
  411.    for (cnt=0; cnt < bubble_cnt; cnt++)
  412.       {
  413.       x[cnt]+=speedx[cnt];            /* move the object */
  414.       y[cnt]+=speedy[cnt];
  415.       gs_anim_obj((struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]);
  416.       if (reset[cnt])               /* since anim doesn't loop, must reset */
  417.          {                           /* the sequence in the event of collision */
  418.          reset[cnt]=0;               /* start at 1st cell in anim sequence */
  419.          gs_set_anim_cell((struct anim_struct *)&bubble[cnt],0);
  420.          }
  421.       if (!bubble[cnt].collide)      /* if not colliding, clear last ptr */
  422.          last[cnt]=-1;
  423.       }
  424.    if (new_line)
  425.       {
  426.       new_line=0;
  427.       x1=gs_random(swidth);
  428.       y1=gs_random(sheight);
  429.       gs_init_vector(0,x1,y1,gs_random(swidth),gs_random(sheight));
  430.       if (first)
  431.          {
  432.          first=0;
  433.          lastx=x1;
  434.          lasty=y1;
  435.          }
  436.       }
  437.    while (bubble_display.flags & GSV_FLIP);   /* while page not flipped yet */
  438.    gs_restore_anim_bg(dlist);         /* restore the background gfx */
  439.    if (display_page)                  /* plot the line behind the bubbles */
  440.       {
  441.       gs_plot(vp.bitmap1,lastx,lasty,1);
  442.       gs_plot(vp.bitmap1,x1,y1,1);
  443.       }
  444.    else
  445.       {
  446.       gs_plot(vp.bitmap2,lastx,lasty,1);
  447.       gs_plot(vp.bitmap2,x1,y1,1);
  448.       }
  449.    lastx=x1;
  450.    lasty=y1;
  451.    gs_step_vector(0,1,&x1,&y1);      /* next point on line */
  452.    if ((x1 == 0) && (y1 == 0))      /* check for end of the line */
  453.       new_line=1;
  454.    gs_draw_anim_objs(dlist);         /* draw the anim objects over the screen */
  455.    check_bounds();                  /* bounce off of outer bitmap bounds */
  456.    gs_next_anim_page(dlist);         /* tell anim sys to use other bitmap */
  457.    gs_flip_display(&bubble_display,1);   /* switch to other display, sync */
  458.    display_page^=1;                  /* keep track of current display page */
  459. }
  460.  
  461. /***************************************************************************/
  462.  
  463. void check_bounds()
  464.  
  465. {
  466.    int cnt;
  467.  
  468.    for (cnt=0; cnt < bubble_cnt; cnt++)
  469.       {
  470.       if (bubble[cnt].flags & (ANIM_BOUNDS_X1|ANIM_BOUNDS_X2))
  471.          {
  472.          x[cnt]=bubble[cnt].x;   /* keep track of current location */
  473.          speedx[cnt]=-speedx[cnt];   /* reverse X direction */
  474.          reset[cnt]=1;            /* make bubble warp */
  475.          last[cnt]=-1;            /* no colliding */
  476.          }
  477.       if (bubble[cnt].flags & (ANIM_BOUNDS_Y1|ANIM_BOUNDS_Y2))
  478.          {
  479.          y[cnt]=bubble[cnt].y;
  480.          speedy[cnt]=-speedy[cnt];   /* reverse Y direction */
  481.          reset[cnt]=1;
  482.          last[cnt]=-1;
  483.          }
  484.       }
  485. }
  486.  
  487. /***************************************************************************/
  488.  
  489. int check_close()
  490.  
  491. /* check for user input */
  492.  
  493. {
  494.    if (gs_joystick(0) & (JOY_BUTTON1|JOY_BUTTON2))
  495.       return(1);
  496.    return(0);
  497. }
  498.  
  499. /***************************************************************************/
  500.  
  501. __stdargs void collision(anim1,anim2,coll1,coll2)
  502. struct anim_struct *anim1;
  503. struct anim_struct *anim2;
  504. struct collision_struct *coll1;
  505. struct collision_struct *coll2;
  506.  
  507. /*
  508.  
  509. This is the collision handler which makes the bubbles "bounce" off of
  510. each other.
  511.  
  512. */
  513.  
  514. {
  515.    int temp;
  516.  
  517.    if (last[anim1->array_num] != anim2->array_num)      /* if not same object */
  518.       {
  519.       last[anim1->array_num] = anim2->array_num;      /* remember last collision */
  520.       last[anim2->array_num] = anim1->array_num;
  521.       reset[anim1->array_num]=1;                        /* reset anim cell */
  522.       reset[anim2->array_num]=1;
  523.       temp=speedy[anim2->array_num];                  /* swap values */
  524.       speedy[anim2->array_num]=speedy[anim1->array_num];
  525.       speedy[anim1->array_num]=temp;
  526.       temp=speedx[anim2->array_num];
  527.       speedx[anim2->array_num]=speedx[anim1->array_num];
  528.       speedx[anim1->array_num]=temp;
  529.       }
  530. }
  531.  
  532. /***************************************************************************/
  533.  
  534. void cleanup()
  535.  
  536. /* release all resources and memory */
  537.  
  538. {
  539.    free_arrays();
  540.    gs_free_anim(bubble,bubble_cnt);
  541.    gs_remove_display(&bubble_display);
  542.    gs_free_display_list(dlist);
  543.    gs_close_vb_timer();
  544. }
  545.  
  546. /***************************************************************************/
  547.  
  548. void free_arrays()
  549.  
  550. /* release memory used by control arrays */
  551.  
  552. {
  553.    if (x)
  554.       free(x);
  555.    if (y)
  556.       free(y);
  557.    if (speedx)
  558.       free(speedx);
  559.    if (speedy)
  560.       free(speedy);
  561.    if (last)
  562.       free(last);
  563.    if (reset)
  564.       free(reset);
  565. }
  566.